package com.fwtai.service.api;

import com.fwtai.api.ApiBuyDao;
import com.fwtai.bean.PageFormData;
import com.fwtai.config.LocalUserId;
import com.fwtai.pay.wechat.sp.ToolSPConstants;
import com.fwtai.pay.wechat.sp.ToolSPWechat;
import com.fwtai.quartz.MallDeleteOrder;
import com.fwtai.quartz.ToolQuartz;
import com.fwtai.service.AsyncService;
import com.fwtai.service.ServiceCouponArea;
import com.fwtai.service.ServiceCouponStore;
import com.fwtai.service.TaskService;
import com.fwtai.tool.IdBuilder;
import com.fwtai.tool.ToolClient;
import com.fwtai.tool.ToolDate;
import com.fwtai.tool.ToolString;
import com.fwtai.web.GoodsAreaDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

@Service
public class ApiBuyService{

  @Value("${notifyPayUrl}")
  private String notifyPayUrl;

  @Value("${notifyActivityUrl}")
  private String notifyActivityUrl;

  @Value("${notifyUrl}")
  private String notifyUrl;

  private final ApiBuyDao apiBuyDao;

  private final GoodsAreaDao goodsAreaDao;

  private final TaskService taskService;

  private final AsyncService asyncService;

  private final ServiceCouponArea serviceCouponArea;

  private final ServiceCouponStore serviceCouponStore;

  private final ThreadPoolTaskExecutor taskExecutor;

  public ApiBuyService(final ApiBuyDao apiBuyDao,final GoodsAreaDao goodsAreaDao,final AsyncService asyncService,final ServiceCouponArea serviceCouponArea,final ServiceCouponStore serviceCouponStore,final TaskService taskService,final ThreadPoolTaskExecutor taskExecutor){
    this.apiBuyDao = apiBuyDao;
    this.goodsAreaDao = goodsAreaDao;
    this.taskService = taskService;
    this.asyncService = asyncService;
    this.serviceCouponArea = serviceCouponArea;
    this.serviceCouponStore = serviceCouponStore;
    this.taskExecutor = taskExecutor;
  }

  public String prePay(final HttpServletRequest request){
    final String loginId = LocalUserId.get();
    if(loginId == null) return ToolClient.accessLogin();
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_openId = "openId";//微信的openId
      final String p_buyer_type = "buyer_type";//购买类型
      final String p_goodsInfo = "goodsInfo";//购买时商品json数组信息
      final String p_storeId = "storeId";//当buyer_type=1时才传值直营门店的主键kid
      final String p_areaUserId = "areaProxyUserId";//当buyer_type=2时才传区代理的用户id(goods_area.user_id)

      final String validate = ToolClient.validateField(formData,p_openId,p_buyer_type,p_goodsInfo);
      if(validate != null)return validate;
      final String fieldInteger = ToolClient.validateInteger(formData,p_buyer_type);
      if(fieldInteger != null)return fieldInteger;
      //格式为购买商品的json数组信息,含商品的id,购买数量number,区域代理的所属用户id,门店id
      final ArrayList<HashMap<String,String>> listGoods = ToolString.parseJsonArray(formData.getString(p_goodsInfo));
      for(int i = listGoods.size() - 1; i >= 0; i--){
        final String bottles = listGoods.get(i).get("category");//区分是1按瓶购买还是2按件购买,消费者默认为1
        if(bottles == null){
          return ToolClient.createJsonFail("购买的参数有误");
        }
      }
      final Integer type = formData.getInteger(p_buyer_type);
      final Long storeKid = formData.getLong(p_storeId);
      final long loginKey = Long.parseLong(loginId);
      switch (type){
        case 1://消费者从直营店购买
          if(storeKid == null){
            return ToolClient.createJsonFail("门店的参数有误");
          }
          for(int a = listGoods.size() - 1; a >= 0; a--){
            final HashMap<String,String> map = listGoods.get(a);
            final String storeGoodsId = map.get("storeGoodsId");
            if(storeGoodsId == null || storeGoodsId.length() == 0){
              return ToolClient.createJsonFail("门店库存的参数有误");
            }
          }
          //购买前,判断消费者一对一绑定直营门店
          final Long storeKey = apiBuyDao.getStoreUser(loginKey);
          if(storeKey != null && !storeKey.equals(storeKid)){
            return ToolClient.createJsonFail("您只能在同一家门店购买");
          }
          break;
        case 2://直营店从区级购买;
          final HashMap<String,String> map2 = listGoods.get(0);
          final String areaGoodsId = map2.get("areaGoodsId");
          if(areaGoodsId == null || areaGoodsId.length() == 0){
            return ToolClient.createJsonFail("区域库存的参数有误");
          }
          break;
        case 3://区级向总公司购买(区代进货)
          break;
        default:
          return ToolClient.jsonValidateField();
      }
      final ArrayList<String> attach = new ArrayList<>(3);
      attach.add(loginId);//下单人(消费者|直营门店的所属人|区级代理商的userId)
      switch (type){
        case 1://1是用户购买
          attach.add(String.valueOf(storeKid));//直营门店的主键kid,用于仅扣减直营门店的库存
          break;
        case 2://2是直营店向区级购买(门店进货)
          attach.add(formData.getString(p_areaUserId));
          break;
        case 3://3区级向总公司购买(区代进货)
          break;
        default:
          return ToolClient.jsonValidateField();
      }
      //存储商品的kid及数量
      final ArrayList<HashMap<Long,HashMap<String,Integer>>> listGoodsInfos = new ArrayList<>(listGoods.size());
      final ArrayList<Long> kids = new ArrayList<>(listGoods.size());
      for(int i = listGoods.size() - 1; i >= 0; i--){
        final HashMap<String,String> goodsInfo = listGoods.get(i);
        final HashMap<Long,HashMap<String,Integer>> infos = new HashMap<>();
        final long goodsId = Long.parseLong(goodsInfo.get("goodsId"));//商品的id
        final HashMap<String,Integer> categoryNumber = new HashMap<>(2);
        final int category = Integer.parseInt(goodsInfo.get("category"));//按件或瓶数
        final int number = Integer.parseInt(goodsInfo.get("number"));//goodsId是商品id,number是商品的数量|件数
        categoryNumber.put("category",category);//按件或瓶数类型
        categoryNumber.put("number",number);//件数或瓶数
        infos.put(goodsId,categoryNumber);//goodsId是商品id,number是商品的数量|件数
        listGoodsInfos.add(infos);
        switch (type){
          case 1:
            kids.add(Long.parseLong(goodsInfo.get("storeGoodsId")));
            break;
          case 2:
            kids.add(Long.parseLong(goodsInfo.get("areaGoodsId")));
            break;
          case 3:
            kids.add(goodsId);
            break;
          default:
            break;
        }
      }
      final List<HashMap<String,Object>> goodsInfo = apiBuyDao.getGoodsType(kids,type);//通过list商品的kid获取商品价格
      final String json = handlerGoods(goodsInfo);//验证库存相关
      if(json != null){
        return json;
      }
      //验证购买的商品的数量是否有足够的库存量
      for(int x = goodsInfo.size() - 1; x >= 0; x--){
        final HashMap<String,Object> map = goodsInfo.get(x);
        final Long kid = (Long) map.get("kid");
        for(int y = listGoodsInfos.size() - 1; y >= 0; y--){
          final HashMap<Long,HashMap<String,Integer>> hashMap = listGoodsInfos.get(y);
          for(final Long key : hashMap.keySet()){
            if(key.equals(kid)){
              if(type != 3){//仅区代进货不验证总公司的库存
                final Integer inventory = (Integer) map.get("inventory");
                final Integer bottles = (Integer) map.get("bottles");
                final HashMap<String,Integer> cn = hashMap.get(key);
                final Integer number = cn.get("number");
                final Integer category = cn.get("category");
                if(category == 1){
                  if(number > inventory){
                    return ToolClient.createJsonFail("商品["+map.get("contract_name")+"]库存量小于购买数量,购买失败");
                  }
                }else{
                  if(number * bottles > inventory){
                    return ToolClient.createJsonFail("商品["+map.get("contract_name")+"]库存量小于购买数量,购买失败");
                  }
                }
              }
            }
          }
        }
      }
      //计算商品的数量及价格
      priceHandler(goodsInfo,listGoodsInfos);
      final long outTradeNo = new IdBuilder().getOrderNumber32L();
      final String openId = formData.getString(p_openId);
      final long kid = new IdBuilder().getId121L();//订单表goods_order的kid
      final HashMap<String,Object> goods_order = new HashMap<>(9);

      goods_order.put("kid",kid);
      goods_order.put("user_id",loginId);
      goods_order.put("buyer_type",type);
      goods_order.put("openId",openId);
      goods_order.put("type",1);
      goods_order.put("out_trade_no",outTradeNo);
      switch (type){
        case 1:
          goods_order.put("payee",apiBuyDao.getStoreBoss(storeKid));
          break;
        case 2:
          goods_order.put("payee",formData.get(p_areaUserId));
          break;
        case 3:
          break;
        default:
          break;
      }
      goods_order.put("body",handlerType(type));
      BigDecimal price = new BigDecimal("0.00");
      for(int x = goodsInfo.size() - 1; x >= 0; x--){
        final BigDecimal free = (BigDecimal) goodsInfo.get(x).get("free");
        price = price.add(free);
      }
      final double intValue = price.doubleValue() * 100;
      final int value = (int)intValue;
      goods_order.put("total_fee",price);

      final HashMap<String,Object> goods_order_log = new HashMap<>(8);

      goods_order_log.put("kid",new IdBuilder().getId121L());
      goods_order_log.put("store_id",storeKid);//消费者购买时才存在门店id
      goods_order_log.put("buyer_id",loginId);
      goods_order_log.put("buyer_type",type);
      goods_order_log.put("out_trade_no",outTradeNo);
      goods_order_log.put("order_id",kid);
      goods_order_log.put("amount",price);
      goods_order_log.put("details",handlerType(type));

      final ArrayList<HashMap<String,Object>> listDetail = new ArrayList<>(listGoods.size());
      final boolean bl = type == 3;//区代进货|区代购买标识
      if(bl){
        final HashMap<String,Object> res = handlerCoupon(goodsInfo,loginKey);
        if((Boolean)res.get("error")){
          return ToolClient.createJsonFail((String) res.get("data"));
        }
      }
      //查询商品当前发放规则
      for(int d = goodsInfo.size() - 1; d >= 0; d--){
        final HashMap<String,Object> map = goodsInfo.get(d);
        final HashMap<String,Object> detail = new HashMap<>(7);
        detail.put("goods_order_id",kid);
        detail.put("goods_id",map.get("kid"));
        detail.put("store_id",storeKid);//消费者购买时才存在门店id
        detail.put("item_fee",map.get("price"));//单个商品的价格
        detail.put("total",map.get("number"));//购买数量
        if(map.containsKey("coupon")){
          detail.put("coupon",map.get("coupon"));//优惠券数量
        }
        final Integer category = (Integer)map.get("category");
        if(category == 2){
          detail.put("bottles",map.get("bottles"));//购买数量
        }else{
          detail.put("bottles",null);
        }
        listDetail.add(detail);
      }
      try {
        final int rows = apiBuyDao.addOrder(goods_order,goods_order_log,listDetail);
        if(rows > 0){
          taskService.delOrderTask(kid);//设定定时30分钟后未支付的订单则删除,当然在支付回调时也可以删除定时任务的!
          final HashMap<String,String> payParams = ToolSPWechat.getParamsOrder(ToolSPConstants.SUB_MCH_ID,openId,String.valueOf(outTradeNo),handlerType(type),notifyPayUrl,value,false,handerAttachs(attach,type));
          return ToolClient.queryJson(payParams);
        }
        return ToolClient.createJsonFail("购买失败,稍候重试");
      } catch (final Exception ignored){
        ignored.printStackTrace();
        return ToolClient.exceptionJson("下单出错,稍候重试");
      }
    },taskExecutor).join();
  }

  public HashMap<String,Object> handlerCoupon(final List<HashMap<String,Object>> goodsInfo,final long loginKey){
    final HashMap<String,Object> result = apiBuyDao.getUserProxyAreaLevel(loginKey);
    final Integer type = (Integer)result.get("type");//其实就是sys_area.level的值
    final boolean custom = result.containsKey("area_id");//是否存在表partner的字段area_id,存在说明所代理的是特殊区域
    final Long areaId = custom ? serviceCouponArea.getAreaId(result,8) : serviceCouponArea.getAreaId(result,type);//传入数字8的目的是拿area_id的值,也就是case的default
    final HashMap<String,Object> res = new HashMap<>(2);
    if(areaId == null){
      res.put("error",true);
      res.put("data","您没有进货权限,请联系管理员");//不是特殊区域的代理
      return res;
    }
    final HashMap<String,Object> params = new HashMap<>(2);
    //获取商品id
    final Long[] goodsIds = new Long[goodsInfo.size()];
    for(int i = goodsInfo.size() - 1; i >= 0; i--){
      goodsIds[i] = (Long) goodsInfo.get(i).get("kid");
    }
    params.put("array",goodsIds);
    final ArrayList<Long> areaIds = new ArrayList<>(4);
    //判断代理商所代理的区域是否是设定为特殊区域,即是否取表partner的字段area_id的值
    if(custom){//是代理的是特殊区域,则通过表partner的字段area_id的值与sys_area查询区域的等级level,然后查询该区域的所有的上级区域,↓↓↓
      final Integer level = goodsAreaDao.getAreaLevel(areaId);//通过表partner的字段area_id的值与sys_area查询区域的等级level,即level的值,然后查询该区域的所有的上级区域,如果level=1时那areaId就是本身
      if(level != 1){//通过areaId查询sys_area的字段level如果不是1则查询该区域的所有的上级区域;如果是1则直接就是省级代理,直接取值即可
        final HashMap<String,Object> areaMap = goodsAreaDao.getAreaCustom(level,areaId);//然后查询该区域的所有的上级区域(即表partner的字段area_id的值)
        if(areaMap == null){
          res.put("error",true);
          res.put("data","代理的区域有误，请联系管理员");
          return res;
        }
        serviceCouponArea.getCustomId(areaMap,level,areaIds);
      }else{
        areaIds.add(areaId);//通过areaId查询sys_area的字段level=1时,那areaId就是本身,直接取值即可
      }
    }else{
      areaIds.add((Long) result.get("province_id"));
      areaIds.add((Long) result.get("city_id"));
      areaIds.add((Long) result.get("county_id"));
    }
    params.put("areaIds",areaIds);
    //通过普通区域省(province_id)、市(city_id)、区(county_id)或特殊区域的area_id的id查询优惠券发放规则表，判断已哪一个规则发放优惠券,只取优惠券表coupon的goods_id和type最大值MAX(type),因为优先级是字段type从大到小
    final List<HashMap<String,Object>> listAreaCoupon = goodsAreaDao.getAreaCoupon(params);//商品id及区域id,获取优惠券规则
    final List<HashMap<String,Object>> list = goodsAreaDao.getGoodsIdsCoupon(goodsIds);//默认的优惠券规则
    if(!listAreaCoupon.isEmpty()){//优惠券设定区域不为空时替换默认的优惠券规则
      serviceCouponArea.replaceCoupon(list,listAreaCoupon);//替换优惠券规则
    }
    for(int x = goodsInfo.size() - 1; x >= 0; x--){
      final HashMap<String,Object> map = goodsInfo.get(x);
      final Object kid = map.get("kid");
      for(int y = list.size() - 1; y >= 0; y--){
        final HashMap<String,Object> hashMap = list.get(y);
        final Object value = hashMap.get("kid");
        if(value.equals(kid)){
          map.put("coupon",hashMap.get("coupon"));
          break;
        }
      }
    }
    res.put("error",false);
    res.put("data",list);
    return res;
  }

  /**使用积分账户购买商品(积分购买)*/
  public String addIntegralBuy(final HttpServletRequest request){
    final String loginId = LocalUserId.get();
    if(loginId == null) return ToolClient.accessLogin();
    return CompletableFuture.supplyAsync(()->{
      final PageFormData formData = new PageFormData(request);
      final String p_buyer_type = "buyer_type";//购买类型
      final String p_areaProxyUserId = "areaProxyUserId";//当buyer_type=2时才传区代理的用户id,即收款人
      final String p_goodsInfo = "goodsInfo";//购买时商品json数组信息
      final String validate = ToolClient.validateField(formData,p_buyer_type,p_goodsInfo);
      if(validate != null)return validate;
      final String fieldInteger = ToolClient.validateInteger(formData,p_buyer_type);
      if(fieldInteger != null)return fieldInteger;
      final ArrayList<HashMap<String,String>> listGoods = ToolString.parseJsonArray(formData.getString(p_goodsInfo));
      for(int i = listGoods.size() - 1; i >= 0; i--){
        final String bottles = listGoods.get(i).get("category");//区分是1按瓶购买还是2按件购买,消费者默认为1
        if(bottles == null){
          return ToolClient.createJsonFail("购买的参数有误");
        }
      }
      final Integer buyerType = formData.getInteger(p_buyer_type);
      switch (buyerType){
        case 2://直营店从区级购买;(门店进货)
          final HashMap<String,String> map2 = listGoods.get(0);
          final String areaGoodsId = map2.get("areaGoodsId");
          if(areaGoodsId == null || areaGoodsId.length() == 0){
            return ToolClient.createJsonFail("区域库存的参数有误");
          }
          break;
        case 3://区级向总公司购买(区代进货)
          break;
        default:
          return ToolClient.jsonValidateField();
      }
      //存储商品的kid及数量
      final ArrayList<HashMap<Long,HashMap<String,Integer>>> listGoodsInfos = new ArrayList<>(listGoods.size());
      final ArrayList<Long> kids = new ArrayList<>(listGoods.size());
      for(int i = listGoods.size() - 1; i >= 0; i--){
        final HashMap<String,String> goodsInfo = listGoods.get(i);
        final HashMap<Long,HashMap<String,Integer>> infos = new HashMap<>();
        final long goodsId = Long.parseLong(goodsInfo.get("goodsId"));//商品的id
        final HashMap<String,Integer> categoryNumber = new HashMap<>(2);
        final int category = Integer.parseInt(goodsInfo.get("category"));//按件或瓶数
        final int number = Integer.parseInt(goodsInfo.get("number"));//goodsId是商品id,number是商品的数量|件数
        categoryNumber.put("category",category);//按件或瓶数类型
        categoryNumber.put("number",number);//件数或瓶数
        infos.put(goodsId,categoryNumber);//goodsId是商品id,number是商品的数量|件数
        listGoodsInfos.add(infos);
        switch (buyerType){
          case 2:
            kids.add(Long.parseLong(goodsInfo.get("areaGoodsId")));
            break;
          case 3:
            kids.add(goodsId);
            break;
          default:
            break;
        }
      }
      final List<HashMap<String,Object>> goodsInfo = apiBuyDao.getGoodsType(kids,buyerType);//通过list商品的kid获取商品价格
      final String json = handlerGoods(goodsInfo);//验证库存相关
      if(json != null){
        return json;
      }
      //验证购买的商品的数量是否有足够的库存量
      for(int x = goodsInfo.size() - 1; x >= 0; x--){
        final HashMap<String,Object> map = goodsInfo.get(x);
        final Long kid = (Long) map.get("kid");
        for(int y = listGoodsInfos.size() - 1; y >= 0; y--){
          final HashMap<Long,HashMap<String,Integer>> hashMap = listGoodsInfos.get(y);
          for(final Long key : hashMap.keySet()){
            if(key.equals(kid)){
              if(buyerType != 3){
                final Integer inventory = (Integer) map.get("inventory");
                final Integer bottles = (Integer) map.get("bottles");
                final HashMap<String,Integer> cn = hashMap.get(key);
                final Integer number = cn.get("number");
                final Integer category = cn.get("category");
                if(category == 1){
                  if(number > inventory){
                    return ToolClient.createJsonFail("商品["+map.get("contract_name")+"]库存量小于购买数量,购买失败");
                  }
                }else{
                  if(number * bottles > inventory){
                    return ToolClient.createJsonFail("商品["+map.get("contract_name")+"]库存量小于购买数量,购买失败");
                  }
                }
              }
            }
          }
        }
      }
      //计算商品的数量及价格
      priceHandler(goodsInfo,listGoodsInfos);
      BigDecimal price = new BigDecimal("0.00");
      for(int x = goodsInfo.size() - 1; x >= 0; x--){
        final BigDecimal free = (BigDecimal) goodsInfo.get(x).get("free");
        price = price.add(free);
      }
      final long loginKey = Long.parseLong(loginId);
      final BigDecimal outRecord = apiBuyDao.getOutTotal(loginKey);//获取待兑换的积分
      BigDecimal total = apiBuyDao.getIntegralTotal(loginKey);
      if(outRecord != null){
        total = total.subtract(outRecord);//可用积分 = 总积分 - 待提现的积分
      }
      if(price.compareTo(total) > 0){
        return ToolClient.createJsonFail("积分不足,可用积分为"+total);
      }
      final long kid = new IdBuilder().getId121L();//表user_integral_buy的kid
      final long out_trade_no = new IdBuilder().getOrderNumber32L();
      final HashMap<String,Object> integralBuy = new HashMap<>(7);
      final Long areaProxyUserId = formData.getLong(p_areaProxyUserId);
      integralBuy.put("kid",kid);
      integralBuy.put("payee",areaProxyUserId);
      integralBuy.put("out_trade_no",out_trade_no);
      integralBuy.put("user_id",loginKey);
      integralBuy.put("score",price);
      integralBuy.put("body","使用积分进货");

      final boolean bl = buyerType == 3;//区代进货|区代购买标识
      if(bl){
        final HashMap<String,Object> res = handlerCoupon(goodsInfo,loginKey);
        if((Boolean)res.get("error")){
          return ToolClient.createJsonFail((String) res.get("data"));
        }
      }

      final ArrayList<HashMap<String,Object>> listIntegralGoods = new ArrayList<>(goodsInfo.size());
      for(int i = goodsInfo.size() - 1; i >= 0; i--){
        final HashMap<String,Object> map = new HashMap<>(6);
        final HashMap<String,Object> hashMap = goodsInfo.get(i);
        map.put("buy_id",kid);
        map.put("goods_id",hashMap.get("kid"));
        map.put("free",hashMap.get("price"));//单件商品的价格
        map.put("total",hashMap.get("number"));//购买的商品数量|件数
        map.put("coupon",hashMap.get("coupon"));//商品优惠券规则
        final Integer category = (Integer)hashMap.get("category");
        if(category == 2){
          map.put("bottles",hashMap.get("bottles"));//购买数量
        }else{
          map.put("bottles",null);
        }
        listIntegralGoods.add(map);
      }
      final int rows = apiBuyDao.addIntegralBuy(integralBuy,listIntegralGoods);
      if(rows > 0){
        asyncService.addDeliveryAuto(out_trade_no,2,null,null);//3天自动确认收货
        final HashMap<String,Object> params = new HashMap<>(5);
        params.put("kid",new IdBuilder().getId121L());
        params.put("score",price);
        params.put("loginId",loginKey);
        params.put("category",2);
        params.put("out_id",out_trade_no);
        apiBuyDao.updateAccount(params);//扣减账户积分
        //后面可能会删除
        final Long storeId = apiBuyDao.getMyStoreId(loginKey);
        if(buyerType == 2){//处理直营门店的商品库存
          final HashMap<String,Object> mapCoupon = new HashMap<>(2);
          mapCoupon.put("storeId",storeId);
          mapCoupon.put("list",goodsInfo);
          final List<Long> list = goodsAreaDao.getStoreGoodsCoupon(mapCoupon);
          if(list.size() != goodsInfo.size()){
            final ArrayList<HashMap<String,Object>> goods = new ArrayList<>(goodsInfo.size());
            if(!list.isEmpty()){
              for(int i = goodsInfo.size() - 1; i >= 0; i--){
                final HashMap<String,Object> m = goodsInfo.get(i);
                final Long id = (Long) m.get("kid");
                for(int y = list.size() - 1; y >= 0; y--){
                  if(!id.equals(list.get(y))){
                    final HashMap<String,Object> map = new HashMap<>(5);
                    map.put("kid",new IdBuilder().getId121L());
                    map.put("store_id",storeId);
                    map.put("goods_id",id);
                    map.put("coupon",m.get("coupon"));
                    map.put("inventory",0);
                    goods.add(map);
                  }
                }
              }
            }else{
              for(int i = goodsInfo.size() - 1; i >= 0; i--){
                final HashMap<String,Object> m = goodsInfo.get(i);
                final HashMap<String,Object> map = new HashMap<>(5);
                map.put("kid",new IdBuilder().getId121L());
                map.put("store_id",storeId);
                map.put("goods_id",m.get("kid"));
                map.put("coupon",m.get("coupon"));
                map.put("inventory",0);
                goods.add(map);
              }
            }
            if(goods.size() > 0){
              apiBuyDao.addStoreGoods(goods);
            }
          }
        }
        if(buyerType == 3){//区级代理的商品库存
          serviceCouponArea.addCoupon(goodsAreaDao.getAreaUserId(loginKey));
        }
        switch (buyerType){
          case 2://直营店从区级代理购买;
            //查询自己的直营店
            final List<HashMap<String,Object>> listInfo2 = new ArrayList<>(goodsInfo.size());
            for(int i = goodsInfo.size() - 1; i >= 0; i--){
              final HashMap<String,Object> hashMap = goodsInfo.get(i);
              final HashMap<String,Object> temp = new HashMap<>(5);
              temp.put("goods_id",hashMap.get("kid"));
              temp.put("coupon",hashMap.get("coupon"));
              temp.put("areaUserId",areaProxyUserId);
              final Integer category = (Integer)hashMap.get("category");
              final Integer number = (Integer)hashMap.get("number");
              if(category == 2){
                final Integer bottles = (Integer)hashMap.get("bottles");
                temp.put("total",number * bottles);
              }else{
                temp.put("total",number);
              }
              temp.put("storeId",storeId);
              listInfo2.add(temp);
            }
            apiBuyDao.updateInventory2(listInfo2);//1.扣减区代理的库存数,2.增加直营门店的库存量
            addBuyIntegral(goodsInfo,loginKey,kid,out_trade_no);//处理分成积分
            addUserSales(areaProxyUserId,price,out_trade_no);
            addUserIntegralBuy(out_trade_no,loginKey);
            break;
          case 3://区级向总公司购买,总公司不需要库存
            //仅增加区商品库存数量
            final List<HashMap<String,Object>> orderInfo3 = new ArrayList<>(goodsInfo.size());
            for(int i = goodsInfo.size() - 1; i >= 0; i--){
              final HashMap<String,Object> map = new HashMap<>(4);
              final HashMap<String,Object> hashMap = goodsInfo.get(i);
              map.put("user_id",loginKey);
              map.put("goods_id",hashMap.get("kid"));
              map.put("coupon",hashMap.get("coupon"));
              final Integer category = (Integer)hashMap.get("category");
              final Integer number = (Integer)hashMap.get("number");
              if(category == 2){
                final Integer bottles = (Integer)hashMap.get("bottles");
                map.put("total",number * bottles);
              }else{
                map.put("total",number);
              }
              orderInfo3.add(map);
            }
            apiBuyDao.updateInventory3(orderInfo3);//扣减库存
            break;
          default:
            break;
        }
      }
      return ToolClient.executeRows(rows);
    },taskExecutor).join();
  }

  //处理分成积分|积分购买
  public void addBuyIntegral(final List<HashMap<String,Object>> goodsInfo,final long loginKey,final Long buyId,final long out_trade_no){
    final List<HashMap<String,Object>> goodsIntegrals = apiBuyDao.getBuyIntegrals(buyId);//此方式支持多种商品的多件商品(即支持购物车)
    //total
    for(int i = goodsInfo.size() - 1; i >= 0; i--){
      final HashMap<String,Object> target = goodsInfo.get(i);
      final Long kid = (Long)target.get("kid");
      for(int x = goodsIntegrals.size() - 1; x >= 0; x--){
        final HashMap<String,Object> mapGoods = goodsIntegrals.get(x);
        final Object goodsId = mapGoods.get("goods_id");
        if(kid.equals(goodsId)){
          mapGoods.put("total",target.get("number"));
        }
      }
    }

    final HashMap<Long,HashMap<Integer,BigDecimal>> mapIntegral = handlerIntegral(goodsIntegrals,"scores");//分成积分
    final ArrayList<HashMap<String,Object>> listData = new ArrayList<>(goodsIntegrals.size());
    for(int x = goodsIntegrals.size() - 1; x >= 0; x--){
      final HashMap<String,Object> temp = goodsIntegrals.get(x);
      final List<HashMap<String,Object>> proxyExist = apiBuyDao.getProxyExist(loginKey);//buyer是直营门店向区级代理进货的下单人
      for(int i = proxyExist.size() - 1; i >= 0; i--){
        final HashMap<String,Object> hashMap = proxyExist.get(i);//user_id
        final HashMap<String,Object> mapData = new HashMap<>(4);
        mapData.put("user_id",hashMap.get("user_id"));
        mapData.put("goods_order_id",buyId);
        final Integer type = (Integer)hashMap.get("type");
        mapData.put("type",type);
        mapData.put("score",handlerLevelIntegral(mapIntegral,(Long) temp.get("goods_id"),type));
        listData.add(mapData);
      }
    }
    final ArrayList<HashMap<String,Object>> listParams = new ArrayList<>(goodsIntegrals.size());
    final Map<Long,List<Map<String,Object>>> objGetMap = listObjGetMap(listData,"user_id");//以user_id分组
    objGetMap.forEach((k,lists)->{
      final HashMap<String,Object> tempMap = new HashMap<>(3);
      tempMap.put("user_id",k);
      BigDecimal totalValue = new BigDecimal(0);//计算总积分
      for(int i = lists.size() - 1; i >= 0; i--){
        final Map<String,Object> objectMap = lists.get(i);
        tempMap.put("kid",new IdBuilder().getId121L());
        tempMap.put("category",2);
        tempMap.put("out_trade_no",out_trade_no);
        totalValue = totalValue.add((BigDecimal) objectMap.get("score"));
        tempMap.put("type",objectMap.get("type"));
      }
      tempMap.put("score",totalValue);
      listParams.add(tempMap);
    });
    apiBuyDao.addProxyIntegral(listParams);
  }

  private String[] handerAttachs(final ArrayList<String> lists,final int type){
    final String[] arrs = new String[1+lists.size()];
    arrs[0] = String.valueOf(type);
    for(int i = 0; i < lists.size(); i++){//注意保证此处的顺序!!!
      arrs[(i + 1)] = lists.get(i);
    }
    return arrs;
  }

  private String handlerType(final int type){
    switch (type){
      case 1:
        return "消费者从直营门店购买";
      case 2:
        return "直营店从区级代理购买";
      case 3:
        return "区级代理向总公司购买";
      default:
        return LocalUserId.get()+"购买商品";
    }
  }

  /**
   * 计算价格及购买数量
   * @param goodsInfo 从数据库查询的数据
   * @param listGoodsInfos 前端提交的数据
  */
  private void handlerPrice(final List<HashMap<String,Object>> goodsInfo,final ArrayList<HashMap<Long,Integer>> listGoodsInfos){
    for(int x = goodsInfo.size() - 1; x >= 0; x--){
      final HashMap<String,Object> mapInfo = goodsInfo.get(x);
      final Long kid = (Long) mapInfo.get("kid");
      for(int y = listGoodsInfos.size() - 1; y >= 0; y--){
        final HashMap<Long,Integer> map = listGoodsInfos.get(y);
        for(final Long key : map.keySet()){
          if(kid.equals(key)){
            final BigDecimal price = (BigDecimal) mapInfo.get("price");
            mapInfo.put("free",price.multiply(new BigDecimal(map.get(key))));//总商品数据价格，单个的全部数量的价格,单个商品总价格
            mapInfo.put("number",map.get(key));//购买数量,json数组里
            break;
          }
        }
      }
    }
  }

  /**
   * 计算价格及购买数量
   * @param goodsInfo 从数据库查询的数据
   * @param listGoodsInfos 前端提交的数据
  */
  private void priceHandler(final List<HashMap<String,Object>> goodsInfo,final ArrayList<HashMap<Long,HashMap<String,Integer>>> listGoodsInfos){
    for(int x = goodsInfo.size() - 1; x >= 0; x--){
      final HashMap<String,Object> mapInfo = goodsInfo.get(x);
      final Long kid = (Long) mapInfo.get("kid");
      for(int y = listGoodsInfos.size() - 1; y >= 0; y--){
        final HashMap<Long,HashMap<String,Integer>> map = listGoodsInfos.get(y);
        for(final Long key : map.keySet()){
          if(kid.equals(key)){
            final BigDecimal price = (BigDecimal) mapInfo.get("price");
            final HashMap<String,Integer> hashMap = map.get(key);
            final Integer category = hashMap.get("category");
            final Integer number = hashMap.get("number");
            mapInfo.put("number",number);//购买数量,json数组里
            mapInfo.put("category",category);//区分是1按瓶购买还是2按件购买,消费者默认为1
            if(category == 1){
              mapInfo.put("free",price.multiply(new BigDecimal(number)));//总商品数据价格，单个的全部数量的价格,单个商品总价格
            }else{
              final Integer bottles = (Integer) mapInfo.get("bottles");
              mapInfo.put("free",price.multiply(new BigDecimal(number * bottles)));//总商品数据价格，单个的全部数量的价格,单个商品总价格
            }
            break;
          }
        }
      }
    }
  }

  //验证选选择的商品是否有效能正常购买
  private String handlerGoods(final List<HashMap<String,Object>> list){
    for(int i = list.size() - 1; i >= 0; i--){
      final HashMap<String,Object> map = list.get(i);
      final Object contractName = map.get("contract_name");
      final Integer inventory = (Integer)map.get("inventory");
      if(inventory <= 0){
        return ToolClient.createJsonFail("商品["+contractName+"]库存不足,购买失败");
      }
      final Integer valid = (Integer)map.get("valid");
      if(valid == 2){
        return ToolClient.createJsonFail("商品["+contractName+"]已下架,购买失败");
      }
      /*final Integer deleted = (Integer)map.get("deleted");
      if(deleted == 0){
        return ToolClient.createJsonFail("商品["+contractName+"]已不存在,购买失败");
      }*/
    }
    return null;
  }

  public String notifyPay(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      try {
        final String notifyInfo = ToolSPWechat.getNotifyInfo(request);
        if(notifyInfo != null){
          final int rows = apiBuyDao.updateOrderStatus(ToolSPWechat.extractParam(notifyInfo));
          final HashMap<String,String> object = ToolString.parseJsonObject(notifyInfo);
          /* transaction_id = #{transaction_id},pay_date = unix_timestamp() where out_trade_no = #{out_trade_no} and total_fee = #{total_fee} and openId = #{openid} and status = 0
            buyer_type=1-->type(购买类型),loginId(下单人),storeId(门店id);
            buyer_type=2-->type(购买类型),loginId(下单人),areaUserId(区代理的用户id也就是goods_area.user_id);
            buyer_type=3-->type(购买类型),loginId(下单人);
          */
          final String[] attachs = object.get("attach").split(",");//数据格式:购买类型,购买人的userId
          final long out_trade_no = Long.parseLong(object.get("out_trade_no"));
          final int type = Integer.parseInt(attachs[0]);//购买类型（1是用户购买；2是直营店向区级购买；3区级向总公司购买）
          final Long loginId = Long.parseLong(attachs[1]);//购买人(下单人)的userId
          //后期可能会删除
          if(type == 3){//区级代理的商品库存
            serviceCouponArea.addCoupon(goodsAreaDao.getAreaUserId(loginId));
          }
          if(type == 2){//处理直营门店的商品库存的新增
            //验证有类型的商品，没有则新增，有则跳过，todo 验证下单的商品及商品的优惠券不一致时替换
            final List<HashMap<String,Object>> maps = serviceCouponStore.getStoreCoupon(goodsAreaDao.getAreaUserId(apiBuyDao.getUserParent(loginId)),loginId,out_trade_no);
            if(maps != null){
              final Long storeKey = apiBuyDao.getMyStoreId(loginId);
              final ArrayList<HashMap<String,Object>> goods = new ArrayList<>(maps.size());
              for(int i = maps.size() - 1; i >= 0; i--){
                final HashMap<String,Object> map = new HashMap<>(5);
                final HashMap<String,Object> m = maps.get(i);
                map.put("kid",new IdBuilder().getId121L());
                map.put("store_id",storeKey);
                map.put("goods_id",m.get("kid"));
                map.put("coupon",m.get("coupon"));
                map.put("inventory",0);
                goods.add(map);
              }
              if(goods.size() > 0){
                apiBuyDao.addStoreGoods(goods);
              }
            }
          }
          /*
          门店进货：
            省代(的分成)、市代(的分成)、区代(区代的本金和分成)
          消费者购买：
            门店的本金和分成、推荐人|事业部的推荐积分
          */
          if(rows > 0){
            final String transactionId = object.get("transaction_id");
            final HashMap<String,String> payer = ToolString.parseJsonObject(object.get("payer"));
            asyncService.addPushDeliverTask(out_trade_no,transactionId,payer.get("sub_openid"));//处理微信端的发货状态及子订单号均改为`待收货`(临时解决方案)
            asyncService.addDeliveryAuto(out_trade_no,1,null,transactionId);//3天自动确认收货
            if(type == 1){
              apiBuyDao.addStoreUser(loginId,Long.parseLong(attachs[2]));//处理消费者和直营门店的一一对一的关系
            }
            switch (type){//处理库存
              case 1://消费者从直营店购买
                final List<HashMap<String,Object>> orderInfo1 = apiBuyDao.getMyOrderInfo(out_trade_no);
                for(int i = orderInfo1.size() - 1; i >= 0; i--){
                  final HashMap<String,Object> map = orderInfo1.get(i);
                  map.put("target",Long.parseLong(attachs[2]));
                }
                apiBuyDao.updateInventory1(orderInfo1);//仅需扣减直营门店的库存
                addUserIntegral(out_trade_no,type);//加门店店主的分成积分
                addOrderDiscount(out_trade_no,loginId,Long.parseLong(attachs[2]));//发放消费者优惠券
                addUserSales(out_trade_no,4);//增加门店本金账户
                break;
              case 2://直营店从区级代理购买(进货) todo 如果存在推荐人再判断是否是事业部用户,如果是则按省级分公司的分成(含佣金和优惠卷分成)
                final List<HashMap<String,Object>> orderInfo2 = apiBuyDao.getMyOrderInfo(out_trade_no);
                //查询自己的直营店
                final Long storeId = apiBuyDao.getMyStoreId(loginId);
                final Long areaUserId = Long.parseLong(attachs[2]);
                for(int b = orderInfo2.size() - 1; b >= 0; b--){
                  final HashMap<String,Object> hashMap = orderInfo2.get(b);
                  final Object bottles = hashMap.get("bottles");
                  hashMap.put("areaUserId",areaUserId);
                  hashMap.put("storeId",storeId);
                  if(bottles != null){
                    final Integer total = (Integer)hashMap.get("total");
                    hashMap.put("total",total * (Integer)bottles);
                  }
                }
                apiBuyDao.updateInventory2(orderInfo2);//1.扣减区代理的库存数,2.增加直营门店的库存量,扣减库存数,数量 x 每件的瓶数
                addUserIntegral(out_trade_no,type);//积分是按本订单所有商品的积分总和,√
                addUserSales(out_trade_no,3);//处理本金,√
                addUserReferrer(out_trade_no,loginId);//添加推荐人积分
                break;
              case 3://区级向总公司购买,总公司不需要库存
                //仅增加区商品库存数量
                final List<HashMap<String,Object>> orderInfo3 = apiBuyDao.getMyOrderInfo(out_trade_no);
                for(int w = orderInfo3.size() - 1; w >= 0; w--){
                  final HashMap<String,Object> hashMap = orderInfo3.get(w);
                  hashMap.put("user_id",loginId);
                  final Object bottles = hashMap.get("bottles");
                  if(bottles != null){
                    final Integer total = (Integer)hashMap.get("total");
                    hashMap.put("total",total * (Integer)bottles);
                  }
                }
                apiBuyDao.updateInventory3(orderInfo3);
                break;
              default:
                break;
            }
            //处理分成积分
            return ToolSPWechat.success();
          }
        }
      } catch (final Exception ignored) {
        ignored.printStackTrace();
      }
      return ToolSPWechat.failure();
    },taskExecutor).join();
  }

  public String activityUrl(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      try {
        final String notifyInfo = ToolSPWechat.getNotifyInfo(request);
        if(notifyInfo != null){
          final int rows = apiBuyDao.updateOrderStatus(ToolSPWechat.extractParam(notifyInfo));
          final HashMap<String,String> object = ToolString.parseJsonObject(notifyInfo);
          final String[] attachs = object.get("attach").split(",");//数据格式:订单id,门店id,活动id,下单人
          final long out_trade_no = Long.parseLong(object.get("out_trade_no"));
          final long orderId = Long.parseLong(attachs[0]);//订单id
          final long storeId = Long.parseLong(attachs[1]);//门店id
          final long activityId = Long.parseLong(attachs[2]);//活动id
          final long loginId = Long.parseLong(attachs[3]);//下单人
          if(rows > 0){
            apiBuyDao.addStoreUser(loginId,storeId);//处理消费者和直营门店的一一对一的关系
            //消费者从直营店购买
            final List<HashMap<String,Object>> orderInfo1 = apiBuyDao.getMyOrderInfo(out_trade_no);
            for(int i = orderInfo1.size() - 1; i >= 0; i--){
              final HashMap<String,Object> map = orderInfo1.get(i);
              map.put("target",storeId);
            }
            apiBuyDao.updateInventory1(orderInfo1);//仅需扣减直营门店的库存
            //①查询门店的商品的利润,②添加门店的订单利润(订单分成)
            final HashMap<String,Object> map = apiBuyDao.getGoodsPromotionIntegral(orderId,activityId);
            final HashMap<String,Object> paramsStore = new HashMap<>(6);
            paramsStore.put("kid",new IdBuilder().getId121L());
            paramsStore.put("user_id",map.get("payee"));
            paramsStore.put("out_trade_no",out_trade_no);
            paramsStore.put("score",map.get("score"));
            paramsStore.put("type",4);//活动订单仅门店有分成利润
            paramsStore.put("category",2);//分成
            apiBuyDao.addStoreIntegral(paramsStore);
            addUserSales(out_trade_no,3);//增加门店本金账户
            //支付成功时移除删除定时任务
            taskService.delJobOrder(orderId);
            asyncService.addActivityRecord(loginId,activityId,orderId,storeId);//活动订单记录,防止一个用户参与一次活动的多次购买
            return ToolSPWechat.success();
          }
        }
      } catch (final Exception ignored) {
        ignored.printStackTrace();
      }
      return ToolSPWechat.failure();
    },taskExecutor).join();
  }

  //本金仅直营门店、区代理
  private void addUserSales(final long out_trade_no,final int type){
    final HashMap<String,Object> map = apiBuyDao.getGoodsOrderFee(out_trade_no);
    final HashMap<String,Object> user_account_in = new HashMap<>(6);
    user_account_in.put("kid",new IdBuilder().getId121L());
    user_account_in.put("user_id",map.get("payee"));
    user_account_in.put("score",map.get("total_fee"));
    user_account_in.put("category",1);
    user_account_in.put("type",type);
    user_account_in.put("out_trade_no",out_trade_no);
    apiBuyDao.addUserSales(user_account_in);
  }

  private void addUserSales(final long payee,final BigDecimal total_fee,final long out_trade_no){
    final HashMap<String,Object> user_account_in = new HashMap<>(6);
    user_account_in.put("kid",new IdBuilder().getId121L());
    user_account_in.put("user_id",payee);
    user_account_in.put("score",total_fee);
    user_account_in.put("category",1);
    user_account_in.put("type",3);
    user_account_in.put("out_trade_no",out_trade_no);
    apiBuyDao.addUserSales(user_account_in);
  }

  private void addUserIntegralBuy(final long out_trade_no,final long buyer){
    //查询区代是否有推荐人,存在就update累加积分
    final List<HashMap<String,Object>> score = apiBuyDao.getIntegralBuyReferrer(out_trade_no);
    final List<HashMap<String,Object>> proxyExist = apiBuyDao.getProxyExist(buyer);//buyer是直营门店向区级代理进货的下单人,payee(区代的收款人),self(自己)
    final ArrayList<Long> users = new ArrayList<>(3);
    for(int x = proxyExist.size() - 1; x >= 0; x--){
      final Long referrer = (Long) proxyExist.get(x).get("referrer");
      if(referrer != null){
        users.add(referrer);
      }
    }
    final List<HashMap<String,Object>> vipIntegral = apiBuyDao.getVipOrder(out_trade_no);//使用积分购买商品的事业部的积分值
    final List<Long> vipUser = users.size() > 0 ? apiBuyDao.getVipUser(users) : null;
    final List<HashMap<String,Object>> list = new ArrayList<>(proxyExist.size());
    for(int i = proxyExist.size() - 1; i >= 0; i--){
      final HashMap<String,Object> map = new HashMap<>(9);
      map.put("kid",new IdBuilder().getId121L());
      final HashMap<String,Object> hashMap = proxyExist.get(i);
      final Long referrer = (Long)hashMap.get("referrer");
      map.put("score",checkVip(vipUser,referrer) ? handlerReferrerScore(vipIntegral) : handlerReferrerScore(score));//score,user_id取值referrer|your_referrals取值self
      map.put("type",checkVip(vipUser,referrer) ? 6 : 5);
      map.put("out_trade_no",out_trade_no);
      map.put("category",4);
      if(referrer != null){
        map.put("user_id",referrer);//获得积分的推荐的userId
      }
      map.put("referrer",hashMap.get("user_id"));//被我推荐的那个人的userId
      list.add(map);
    }
    final List<HashMap<String,Object>> params = new ArrayList<>(proxyExist.size());
    list.forEach(mapRemove->{
      if(mapRemove.containsKey("user_id")){//仅过滤存在推荐人
        params.add(mapRemove);
      }
    });
    if(params.size() > 0){
      apiBuyDao.addReferrer(params);
    }
  }

  //处理推荐人及事业部的总积分[订单分成总积分]
  private BigDecimal handlerReferrerScore(final List<HashMap<String,Object>> list){
    BigDecimal allScore = new BigDecimal("0.00");
    for(int i = list.size() - 1; i >= 0; i--){
      final HashMap<String,Object> hashMap = list.get(i);
      final Object bottles = hashMap.get("bottles");
      final BigDecimal _score = (BigDecimal)hashMap.get("score");
      final Integer total = (Integer)hashMap.get("total");
      if(bottles != null){
        final BigDecimal free = _score.multiply(new BigDecimal(total * (Integer) bottles));
        allScore = allScore.add(free);
      }else{
        final BigDecimal free = _score.multiply(new BigDecimal(total));
        allScore = allScore.add(free);
      }
    }
    return allScore;
  }

  //门店向区代理进货,购买类型为2
  private void addUserReferrer(final long out_trade_no,final long buyer){
    //查询事业部积分总值
    final List<HashMap<String,Object>> vipMap = apiBuyDao.getVipIntegral(out_trade_no);//事业部的积分值，gil.score,god.total,god.bottles
    final List<HashMap<String,Object>> score = apiBuyDao.getGoodsReferrerIntegral(out_trade_no);
    //查询区代是否有推荐人,存在就update累加积分
    final List<HashMap<String,Object>> proxyExist = apiBuyDao.getProxyExist(buyer);//buyer是直营门店向区级代理进货的下单人,payee(区代的收款人),self(自己)
    //查询区代是否有推荐人且推荐人是事业部用户
    final ArrayList<Long> users = new ArrayList<>(3);
    for(int x = proxyExist.size() - 1; x >= 0; x--){
      final Long referrer = (Long) proxyExist.get(x).get("referrer");
      if(referrer != null){
        users.add(referrer);
      }
    }
    final List<Long> vipUser = users.size() > 0 ? apiBuyDao.getVipUser(users) : null;
    final List<HashMap<String,Object>> list = new ArrayList<>(proxyExist.size());
    for(int i = proxyExist.size() - 1; i >= 0; i--){
      final HashMap<String,Object> hashMap = proxyExist.get(i);
      final HashMap<String,Object> map = new HashMap<>(8);
      final Long referrer = (Long)hashMap.get("referrer");
      map.put("kid",new IdBuilder().getId121L());
      if(referrer != null){
        map.put("user_id",referrer);
      }
      map.put("score",checkVip(vipUser,referrer) ? handlerReferrerScore(vipMap) : handlerReferrerScore(score));//score,user_id取值referrer|your_referrals取值self
      map.put("category",4);
      map.put("referrer",hashMap.get("user_id"));
      map.put("type",checkVip(vipUser,referrer) ? 6 : 5);
      map.put("out_trade_no",out_trade_no);
      list.add(map);
    }
    final List<HashMap<String,Object>> params = new ArrayList<>(list.size());
    list.forEach(mapRemove->{
      if(mapRemove.containsKey("user_id")){//仅过滤存在推荐人
        params.add(mapRemove);
      }
    });
    if(params.size() > 0){
      apiBuyDao.addReferrer(params);//添加推荐人积分
    }
  }

  public boolean checkVip(final List<Long> vipUser,final Long referrer){
    if(vipUser == null) return false;
    for(int i = vipUser.size() - 1; i >= 0; i--){
      if(vipUser.get(i).equals(referrer)){
        return true;
      }
    }
    return false;
  }

  ArrayList<Long> handlerMap(final HashMap<String,Object> hashMap,final String... key){
    final ArrayList<Long> list = new ArrayList<>(key.length);
    for(int i = key.length - 1; i >= 0; i--){
      list.add((Long) hashMap.get(key[i]));
    }
    return list;
  }

  /**按订单发放优惠券，仅消费者优惠券*/
  public void addOrderDiscount(final long out_trade_no,final Long loginId,final Long storeId){
    final Long userId = apiBuyDao.getStoreUserId(storeId);//店主userId
    final List<HashMap<String,Object>> listGoods = apiBuyDao.getOrderGoodsInfo(out_trade_no);//pr.province_id,pr.city_id,pr.county_id,pr.area_id,god.goods_id
    final HashMap<String,Object> hashMap = listGoods.get(0);
    final ArrayList<Long> goodsData = new ArrayList<>();//全部的商品id
    for(int x = listGoods.size() - 1; x >= 0; x--){
      goodsData.add((Long) listGoods.get(x).get("goods_id"));
    }
    if(hashMap.containsKey("area_id")){//代理的区域为特殊区域
      final ArrayList<Long> areaIds = new ArrayList<>(4);
      final Long areaId = (Long)hashMap.get("area_id");
      final Integer level = goodsAreaDao.getAreaLevel(areaId);//通过表partner的字段area_id的值与sys_area查询区域的等级level,即level的值,然后查询该区域的所有的上级区域,如果level=1时那areaId就是本身
      if(level != 1){//通过areaId查询sys_area的字段level如果不是1则查询该区域的所有的上级区域;如果是1则直接就是省级代理,直接取值即可
        final HashMap<String,Object> areaMap = goodsAreaDao.getAreaCustom(level,areaId);//然后查询该区域的所有的上级区域(即表partner的字段area_id的值)
        if(areaMap != null){
          serviceCouponArea.getCustomId(areaMap,level,areaIds);
        }
      }else{
        areaIds.add(areaId);//通过areaId查询sys_area的字段level=1时,那areaId就是本身,直接取值即可
      }
      //areaIds 得到区域的id
      handlerNumber(goodsData,areaIds,out_trade_no,loginId,storeId,userId);
    }else{
      final ArrayList<Long> longs = handlerMap(hashMap,"province_id","city_id","county_id");
      handlerNumber(goodsData,longs,out_trade_no,loginId,storeId,userId);
    }
  }

  void handlerNumber(final ArrayList<Long> goodsData,final ArrayList<Long> longs,final long out_trade_no,final Long loginId,final Long storeId,final long userId){
    final ArrayList<HashMap<String,Object>> lt = new ArrayList<>(goodsData.size() * longs.size());
    for(int x = goodsData.size() - 1; x >= 0; x--){
      final Long item = goodsData.get(x);
      for(int y = longs.size() - 1; y >= 0; y--){
        final Long areaId = longs.get(y);
        final HashMap<String,Object> map = new HashMap<>(2);
        map.put("goods_id",item);
        map.put("area_id",areaId);
        lt.add(map);
      }
    }
    final Integer total = apiBuyDao.getGoodsCoupon(lt);
    if(total != null){
      addDiscountNumber(out_trade_no,loginId,storeId,userId,total);
    }else{
      addDiscountNumber(out_trade_no,loginId,storeId,userId,apiBuyDao.getCoupon(goodsData));
    }
  }

  void addDiscountNumber(final long out_trade_no,final Long loginId,final Long storeId,final long userId,final int coupon){
    final ArrayList<HashMap<String,String>> lists = ToolDate.getMonths(coupon);
    final ArrayList<HashMap<String,Object>> list = new ArrayList<>(lists.size());
    for(int x = lists.size() - 1; x >= 0; x--){
      final HashMap<String,String> values = lists.get(x);
      final HashMap<String,Object> map = new HashMap<>(7);
      map.put("kid",new IdBuilder().getId121L());
      map.put("out_trade_no",out_trade_no);
      map.put("store_id",storeId);
      map.put("store_user",userId);
      map.put("validity_start",values.get("validity_start"));
      map.put("validity_end",values.get("validity_end"));
      map.put("user_id",loginId);
      list.add(map);
    }
    apiBuyDao.addGoodsSecurities(list);
  }

  /**添加门店和区级代理的利润（积分）、省、市分公司的佣金*/
  public void addUserIntegral(final long out_trade_no,final int type){
    //查询直营门店的订单是否存在区级代理、市分公司、省分公司
    switch (type){
      case 1://消费者购买门店商品，对应门店拿商品本金[订单金额]+后台设置的商品门店积分（统计消费者购买的商品总数计算总积分）。断层计算，与省市区无关。
        final List<HashMap<String,Object>> listGoodsIntegral = apiBuyDao.getBuyGoodsIntegral(out_trade_no);
        final HashMap<String,Object> objs = listGoodsIntegral.get(0);
        final Long userId = (Long)objs.get("user_id");//店主
        BigDecimal price = new BigDecimal("0.00");
        for(int a = listGoodsIntegral.size() - 1; a >= 0; a--){
          final HashMap<String,Object> goodsIntegral = listGoodsIntegral.get(a);
          final Integer total = (Integer)goodsIntegral.get("total");//购买商品数量
          final String levels = (String)goodsIntegral.get("levels");//商品分成积分等级
          final String scores = (String)goodsIntegral.get("scores");//购买商品积分数
          final String[] arrsLevel = levels.split(",");
          final String[] arrScore = scores.split(",");
          final HashMap<String,BigDecimal> map = new HashMap<>(arrsLevel.length);
          for(int i = arrsLevel.length - 1; i >= 0; i--){
            map.put(arrsLevel[i],new BigDecimal(arrScore[i]).multiply(new BigDecimal(total)));
          }
          price = price.add(map.get("4"));
        }
        final HashMap<String,Object> paramsStore = new HashMap<>(3);
        paramsStore.put("kid",new IdBuilder().getId121L());
        paramsStore.put("user_id",userId);
        paramsStore.put("out_trade_no",out_trade_no);
        paramsStore.put("score",price);
        paramsStore.put("type",4);//消费者向门店购买，仅门店有分成利润
        paramsStore.put("category",2);
        apiBuyDao.addStoreIntegral(paramsStore);
        break;
      case 2://直营门店向区级进货,区代理、市分公司、省分公司如果存在就添加积分,可能会丢失订单的分成积分,则单独处理
        final List<HashMap<String,Object>> goodsIntegrals = apiBuyDao.getGoodsIntegral(out_trade_no);//此方式支持多种商品的多件商品(即支持购物车)
        final HashMap<Long,HashMap<Integer,BigDecimal>> mapIntegral = handlerIntegral(goodsIntegrals,"scores");//分成积分
        final ArrayList<HashMap<String,Object>> listData = new ArrayList<>(goodsIntegrals.size());
        for(int x = goodsIntegrals.size() - 1; x >= 0; x--){
          final HashMap<String,Object> temp = goodsIntegrals.get(x);
          final List<HashMap<String,Object>> proxyExist = apiBuyDao.getProxyExist((Long) temp.get("buyer"));//buyer是直营门店向区级代理进货的下单人
          for(int i = proxyExist.size() - 1; i >= 0; i--){
            final HashMap<String,Object> hashMap = proxyExist.get(i);//user_id
            final HashMap<String,Object> mapData = new HashMap<>(4);
            mapData.put("user_id",hashMap.get("user_id"));
            mapData.put("goods_order_id",temp.get("goods_order_id"));
            final Integer _type = (Integer)hashMap.get("type");
            mapData.put("type",_type);
            mapData.put("score",handlerLevelIntegral(mapIntegral,(Long) temp.get("goods_id"),_type));
            listData.add(mapData);
          }
        }
        final ArrayList<HashMap<String,Object>> listParams = new ArrayList<>(goodsIntegrals.size());
        final Map<Long,List<Map<String,Object>>> objGetMap = listObjGetMap(listData,"user_id");//以user_id分组
        objGetMap.forEach((k,lists)->{
          final HashMap<String,Object> tempMap = new HashMap<>(3);
          tempMap.put("user_id",k);
          BigDecimal totalValue = new BigDecimal(0);//计算总积分
          for(int i = lists.size() - 1; i >= 0; i--){
            final Map<String,Object> objectMap = lists.get(i);
            tempMap.put("kid",new IdBuilder().getId121L());
            tempMap.put("category",2);
            tempMap.put("out_trade_no",out_trade_no);
            totalValue = totalValue.add((BigDecimal) objectMap.get("score"));
            tempMap.put("type",objectMap.get("type"));
          }
          tempMap.put("score",totalValue);
          listParams.add(tempMap);
        });
        apiBuyDao.addProxyIntegral(listParams);
        break;
      case 3:
        break;
      default:
        break;
    }
  }

  public Map<Long,List<Map<String,Object>>> listObjGetMap(final ArrayList<HashMap<String,Object>> list,final String field){
    return list.stream().collect(groupingBy(map -> (Long) map.get(field)));
  }

  private BigDecimal handlerTotal(final HashMap<Long,HashMap<Integer,BigDecimal>> mapIntegral,final Integer level){
    BigDecimal total = new BigDecimal("0.00");
    for(final Long key : mapIntegral.keySet()){
      final HashMap<Integer,BigDecimal> map = mapIntegral.get(key);
      for(final Integer k : map.keySet()){
        if(k.equals(level)){
          total = total.add(map.get(level));
          break;
        }
      }
    }
    return total;
  }

  //拆解商品对应的等级分成积分数或优惠券积分数,等级积分乘以购买的商品数量
  public HashMap<Long,HashMap<Integer,BigDecimal>> handlerIntegral(final List<HashMap<String,Object>> goodsIntegrals,final String mapKey){
    final HashMap<Long,HashMap<Integer,BigDecimal>> map = new HashMap<>(goodsIntegrals.size());
    goodsIntegrals.forEach(m->{
      final String levels = (String)m.get("levels");
      Integer total = (Integer)m.get("total");
      final Object bottles = m.get("bottles");
      final String scores = (String)m.get(mapKey);//scores|discounts
      final String[] arrsLevels = levels.split(",");
      final String[] arrsScores = scores.split(",");
      final HashMap<Integer,BigDecimal> ib = new HashMap<>(arrsLevels.length);
      if(bottles != null){//仅处理当前的商品是按件购买
        total = total * (Integer)bottles;
      }
      for(int x = 0; x < arrsLevels.length; x++){
        ib.put(Integer.parseInt(arrsLevels[x]),new BigDecimal(arrsScores[x]).multiply(new BigDecimal(total)));
      }
      map.put((Long)m.get("goods_id"),ib);
    });
    return map;
  }

  //处理代理等级对应的积分数,通过商品的id及对应的等级获取对应的积分数
  private BigDecimal handlerLevelIntegral(final HashMap<Long,HashMap<Integer,BigDecimal>> map,final Long goodsId,final Integer level){
    return map.get(goodsId).get(level);
  }

  public String addActivityOrder(final HttpServletRequest request){
    final String loginId = LocalUserId.get();
    return CompletableFuture.supplyAsync(()->{
      if(loginId == null) return ToolClient.accessLogin();
      final PageFormData formData = new PageFormData(request);
      final String p_openId = "openId";//微信的openId
      final String p_buyer_type = "buyer_type";//购买类型
      final String p_goodsInfo = "goodsInfo";//购买时商品json数组信息
      final String p_storeId = "storeId";//当buyer_type=1时才传值直营门店的主键kid
      final String p_activityId = "activityId";//当buyer_type=1时才传值直营门店的主键kid
      final String validate = ToolClient.validateField(formData,p_openId,p_buyer_type,p_goodsInfo,p_activityId);
      if(validate != null)return validate;
      final String fieldInteger = ToolClient.validateInteger(formData,p_buyer_type);
      if(fieldInteger != null)return fieldInteger;
      //格式为购买商品的json数组信息,含商品的id,购买数量number,区域代理的所属用户id,门店id
      final ArrayList<HashMap<String,String>> listGoods = ToolString.parseJsonArray(formData.getString(p_goodsInfo));
      final Long storeKid = formData.getLong(p_storeId);
      final HashMap<String,String> map1 = listGoods.get(0);
      final String storeGoodsId = map1.get("storeGoodsId");
      if(storeGoodsId == null || storeGoodsId.length() == 0){
        return ToolClient.createJsonFail("门店库存的参数有误");
      }
      final Long activityId = formData.getLong(p_activityId);
      final HashMap<String,Object> activityInfo = apiBuyDao.getActivityInfo(activityId);
      final Integer deleted = (Integer)activityInfo.get("deleted");
      if(1 == deleted){
        return ToolClient.createJsonFail("活动已下架");
      }
      final Long current = (Long)activityInfo.get("current");
      final Long start = (Long)activityInfo.get("start_date");
      final Long end_date = (Long)activityInfo.get("end_date");
      if(current - start < 0){
        return ToolClient.createJsonFail("活动尚未开始");
      }
      if(end_date - current < 0){
        return ToolClient.createJsonFail("活动已结束");
      }
      final Long loginKey = Long.parseLong(loginId);
      //购买前,判断消费者一对一绑定直营门店
      final Long storeKey = apiBuyDao.getStoreUser(loginKey);
      if(storeKey != null && !storeKey.equals(storeKid)){
        return ToolClient.createJsonFail("您只能在同一家门店购买");
      }
      //购买前,判断消费者是否已购买过活动商品
      final boolean record = apiBuyDao.getActivityRecord(loginKey,activityId);
      if(record){
        return ToolClient.createJsonFail("一个活动仅能参与一次");
      }
      //附加参数时需要附加`订单的id`
      //需要插入的表:goods_order、goods_order_detail、goods_order_log、购买成功后回调时才插入此表order_activity_record
      //存储商品的kid及数量
      final ArrayList<HashMap<Long,Integer>> listGoodsInfos = new ArrayList<>(listGoods.size());
      final ArrayList<Long> kids = new ArrayList<>(listGoods.size());
      for(int i = listGoods.size() - 1; i >= 0; i--){
        final HashMap<String,String> goodsInfo = listGoods.get(i);
        final HashMap<Long,Integer> infos = new HashMap<>();
        final long goodsId = Long.parseLong(goodsInfo.get("goodsId"));//商品的id
        infos.put(goodsId,Integer.parseInt(goodsInfo.get("number")));//goodsId是商品id,number是商品的数量
        listGoodsInfos.add(infos);
        kids.add(goodsId);
      }
      final List<HashMap<String,Object>> goodsInfo = apiBuyDao.getActivityGoods(kids,activityId,storeKid);//通过list商品的kid获取商品价格
      if(goodsInfo.size() == 0){
        return ToolClient.createJsonFail("选择商品门店有误");
      }
      final String json = handlerGoods(goodsInfo);//验证库存相关
      if(json != null){
        return json;
      }
      //验证购买的商品的数量是否有足够的库存量
      for(int x = goodsInfo.size() - 1; x >= 0; x--){
        final HashMap<String,Object> map = goodsInfo.get(x);
        final Long kid = (Long) map.get("kid");
        for(int y = listGoodsInfos.size() - 1; y >= 0; y--){
          final HashMap<Long,Integer> hashMap = listGoodsInfos.get(y);
          for(final Long key : hashMap.keySet()){
            if(key.equals(kid)){
              final Integer inventory = (Integer) map.get("inventory");
              final Integer number = hashMap.get(key);
              if(number > inventory){
                return ToolClient.createJsonFail("商品["+map.get("contract_name")+"]库存量小于购买数量,购买失败");
              }
            }
          }
        }
      }
      //计算商品的数量及价格
      handlerPrice(goodsInfo,listGoodsInfos);
      final long outTradeNo = new IdBuilder().getOrderNumber32L();
      final String openId = formData.getString(p_openId);
      final Long kid = new IdBuilder().getId121L();//订单表goods_order的kid
      final HashMap<String,Object> goods_order = new HashMap<>(9);
      final String[] attach = new String[4];//[顺序:订单id,门店id,活动id,下单人]
      attach[0] = String.valueOf(kid);//订单id
      attach[1] = String.valueOf(storeKid);//门店id
      attach[2] = String.valueOf(activityId);//活动id
      attach[3] = loginId;//下单人
      goods_order.put("kid",kid);
      goods_order.put("user_id",loginId);
      goods_order.put("buyer_type",1);//仅有消费者购买
      goods_order.put("openId",openId);
      goods_order.put("type",2);//活动订单类型
      goods_order.put("out_trade_no",outTradeNo);
      goods_order.put("payee",apiBuyDao.getStoreBoss(storeKid));
      goods_order.put("body",handlerType(1));
      BigDecimal price = new BigDecimal("0.00");
      for(int x = goodsInfo.size() - 1; x >= 0; x--){
        final BigDecimal free = (BigDecimal) goodsInfo.get(x).get("free");
        price = price.add(free);
      }
      final double intValue = price.doubleValue() * 100;
      final int value = (int)intValue;
      goods_order.put("total_fee",price);

      final HashMap<String,Object> goods_order_log = new HashMap<>(8);

      goods_order_log.put("kid",new IdBuilder().getId121L());
      goods_order_log.put("store_id",storeKid);//消费者购买时才存在门店id
      goods_order_log.put("buyer_id",loginId);
      goods_order_log.put("buyer_type",1);
      goods_order_log.put("out_trade_no",outTradeNo);
      goods_order_log.put("order_id",kid);
      goods_order_log.put("amount",price);
      goods_order_log.put("details",handlerType(1));

      final ArrayList<HashMap<String,Object>> listDetail = new ArrayList<>(listGoods.size());

      for(int d = goodsInfo.size() - 1; d >= 0; d--){
        final HashMap<String,Object> map = goodsInfo.get(d);
        final HashMap<String,Object> detail = new HashMap<>(5);
        detail.put("goods_order_id",kid);
        detail.put("goods_id",map.get("kid"));
        detail.put("store_id",storeKid);//消费者购买时才存在门店id
        detail.put("item_fee",map.get("price"));//单个商品的价格
        detail.put("total",map.get("number"));//购买数量
        listDetail.add(detail);
      }
      try {
        final int rows = apiBuyDao.addOrder(goods_order,goods_order_log,listDetail);
        if(rows > 0){
          taskService.delOrderTask(kid);//设定定时30分钟后未支付的订单则删除,当然在支付回调时也可以删除定时任务的!
          final HashMap<String,String> payParams = ToolSPWechat.getParamsOrder(ToolSPConstants.SUB_MCH_ID,openId,String.valueOf(outTradeNo),handlerType(1),notifyActivityUrl,value,false,attach);
          return ToolClient.queryJson(payParams);
        }
        return ToolClient.createJsonFail("购买失败,稍候重试");
      } catch (final Exception ignored){
        ignored.printStackTrace();
        return ToolClient.exceptionJson("下单出错,稍候重试");
      }
    },taskExecutor).join();
  }

  public String addOrder(final HttpServletRequest request,final String mode){
    final Long loginId = LocalUserId.getLong();
    return CompletableFuture.supplyAsync(()->{
      if(loginId == null){
        return ToolClient.accessLogin();
      }
      switch (mode){
        case "1":
        case "2":
          break;
        default:
          return ToolClient.createJsonFail("购买失败,非法参数");
      }
      final PageFormData formData = new PageFormData(request,4);
      final String p_openId = "openId";//微信的openId
      final String p_addressId = "addressId";//收货地址
      final String p_orderInfo = "orderInfo";//订单的json信息
      final String validate = ToolClient.validateField(formData,p_openId,p_orderInfo,p_addressId);
      if(validate != null)return validate;
      final Long addressId = formData.getLong(p_addressId);//收货地址
      if(addressId == null){
        return ToolClient.jsonValidateField("用户的收货地址为空");
      }
      final String orderList = formData.getString(p_orderInfo);
      final ArrayList<HashMap<String,String>> listOrder = ToolString.parseJsonArray(orderList);
      //校验必要的字段且有效数据
      for(int a = listOrder.size() - 1; a >= 0; a--){
        final HashMap<String,String> map = listOrder.get(a);
        if(!map.containsKey("spec_id")){
          return ToolClient.jsonValidateField("商品规格有误");
        }
        if(!map.containsKey("number")){
          return ToolClient.jsonValidateField("购买数量有误");
        }
        try {
          final int number = Integer.parseInt(map.get("number"));
          if(number <= 0){
            return ToolClient.jsonValidateField("数量不能小于1");
          }
          Long.parseLong(map.get("spec_id"));
        } catch (final Exception ignored) {
          return ToolClient.jsonValidateField("商品的规格参数有误");
        }
      }
      final ArrayList<HashMap<String,Object>> listParams = new ArrayList<>(listOrder.size());
      for(int x = listOrder.size() - 1; x >= 0; x--){
        final HashMap<String,String> map = listOrder.get(x);
        final HashMap<String,Object> value = new HashMap<>(2);
        value.put("spec_id",Long.parseLong(map.get("spec_id")));//商品产品规格的id,因为有价格和库存量
        value.put("number",Integer.parseInt(map.get("number")));
        listParams.add(value);
      }
      handlerPriceInventory(listParams);//查询价格并与之对应的库存注入进去+处理每个价格及库存量
      //验证库存
      final String inventory = examineInventory(listParams);
      if(inventory != null){
        return inventory;
      }
      //计算总价格,每种商品的数量的价格总和
      BigDecimal price = new BigDecimal("0.00");
      for(int x = listParams.size() - 1; x >= 0; x--){
        final HashMap<String,Object> map = listParams.get(x);
        final BigDecimal free = (BigDecimal)map.get("price");//单价
        final Integer number = (Integer) map.get("number");//数量
        price = price.add(free.multiply(new BigDecimal(number)));
      }
      final double intValue = price.doubleValue() * 100;//微信支付的单位是分,需要 x100
      final int total = (int) intValue;
      if(total == 0){
        return ToolClient.createJsonFail("价格为0.00元,请联系管理员");
      }
      final boolean mode2 = "2".equals(mode);//积分支付
      if(mode2){
        final BigDecimal IntegralTotal = apiBuyDao.getIntegralTotal(loginId);
        if(price.compareTo(IntegralTotal) > 0){
          return ToolClient.createJsonFail("积分不足,可用积分为"+IntegralTotal);
        }
      }
      final String openId = formData.getString(p_openId);
      final long orderId = new IdBuilder().getId121L();
      final long outTradeNo = new IdBuilder().getId121L();
      final long add_date = System.currentTimeMillis() / 1000;
      final long expires_date = add_date + 2100;// 35分钟 = 2100 = 60 x 35
      final int allTotal = listOrder.stream().mapToInt(m -> Integer.parseInt(m.get("number"))).sum();
      final String description = getBody(mode,allTotal);
      //微信支付不需要插入到订单日志表mall_order_log,但要添加在积分支出明细user_account_out
      final HashMap<String,Object> order_info = new HashMap<>(11);
      order_info.put("kid",orderId);
      order_info.put("user_id",loginId);
      order_info.put("openid",openId);
      order_info.put("out_trade_no",outTradeNo);
      order_info.put("type",Integer.parseInt(mode));
      if(mode2){
        order_info.put("status",1);//已支付
      }
      order_info.put("total_fee",price);
      order_info.put("body",description);
      order_info.put("address_id",addressId);
      order_info.put("add_date",add_date);
      order_info.put("expires_date",expires_date);
      //订单详情，mall_order_detail
      final ArrayList<HashMap<String,Object>> order_detail = new ArrayList<>(listOrder.size());
      for(int x = listParams.size() - 1; x >= 0; x--){
        final HashMap<String,Object> map = listParams.get(x);
        final HashMap<String,Object> detail = new HashMap<>(9);
        detail.put("kid",new IdBuilder().getId121L());
        detail.put("out_trade_no",outTradeNo);
        detail.put("goods_id",map.get("goods_id"));
        detail.put("goods_img",map.get("goods_img"));
        detail.put("spec_img",map.get("spec_img"));
        detail.put("spec_id",map.get("spec_id"));
        detail.put("spec_name",map.get("spec_name"));
        detail.put("item_fee",map.get("price"));
        detail.put("number",map.get("number"));
        order_detail.add(detail);
      }
      //订单日志表，mall_order_log
      final HashMap<String,Object> order_log = new HashMap<>(8);
      order_log.put("kid",new IdBuilder().getId121L());
      order_log.put("user_id",loginId);
      order_log.put("orderInfo",ToolClient.jsonArray(listParams));
      order_log.put("out_trade_no",outTradeNo);
      order_log.put("total_fee",price);
      order_log.put("body",description);
      order_log.put("add_date",add_date);
      order_log.put("expires_date",expires_date);
      if(mode2){//积分支付,不需要自动确认收货,但是微信支付订单要推送到微信服务器发货信息
        order_info.put("pay_date",add_date);//积分支付时的支付时间
        final HashMap<String,Object> account_out = new HashMap<>(5);
        account_out.put("kid",new IdBuilder().getId121L());
        account_out.put("user_id",loginId);
        account_out.put("out_id",outTradeNo);
        account_out.put("score",price);
        account_out.put("category",3);
        final int rows = apiBuyDao.addMallOrder(order_info,order_detail,order_log,account_out);
        //处理3天后自动收货
        if(rows > 0){
          asyncService.addAutoDelivery(outTradeNo,2,null,null);//3天自动确认收货
        }
        return ToolClient.executeRows(rows);
      }else{
        final int rows = apiBuyDao.addMallOrder(order_info,order_detail,order_log);
        if(rows > 0){
          final ArrayList<String> attach = new ArrayList<>(2);//数据格式:订单号、下单人;
          try {
            attach.add(String.valueOf(outTradeNo));//订单编号
            attach.add(String.valueOf(loginId));//下单人
            final HashMap<String,String> payParams = ToolSPWechat.getParamsOrder(ToolSPConstants.SUB_MCH_ID,openId,String.valueOf(outTradeNo),description,notifyUrl,total,false,String.join(",",attach).split(","));
            if(payParams.containsKey("fail")){
              return ToolClient.createJsonFail(payParams.get("message"));
            }
            //加入到35分钟后未支付的订单删除即可
            asyncService.delMallOrderInfo(outTradeNo);//设定定时30分钟后未支付的订单则删除,当然在支付回调时也可以删除定时任务的!
            return ToolClient.queryJson(payParams);
          } catch (final Exception exception) {
            exception.printStackTrace();
            return ToolClient.createJsonFail("服务出现错误,稍候再购买");
          }
        }
        return ToolClient.createJsonFail("购买失败,稍候再购买");
      }
    },taskExecutor).join();
  }


  /**
   * ①查询商品的价格并自动处理与之对应的库存注入进去,若不存在库存量时则不处理
   * @param listParams 含kid,price,inventory(库存),goodsName的列表
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2024-02-02 14:21:37
  */
  private void handlerPriceInventory(final List<HashMap<String,Object>> listParams){
    final List<HashMap<String,Object>> listDB = apiBuyDao.getGoodsPrice(listParams.stream().map(m -> (Long) m.get("spec_id")).collect(Collectors.toList()));
    for(int x = listParams.size() - 1; x >= 0; x--){
      final HashMap<String,Object> mapParams = listParams.get(x);
      final Long specId = (Long) mapParams.get("spec_id");
      for(int y = listDB.size() - 1; y >= 0; y--){
        final HashMap<String,Object> mapDB = listDB.get(y);
        final Long kid = (Long) mapDB.get("kid");//从数据库里查询的商品规格的kid，要一一对比
        if(specId.equals(kid)){
          mapParams.put("price",mapDB.get("price"));//价格
          mapParams.put("goodsName",mapDB.get("goodsName"));//第2个参数是查询数据库返回的含有的字段,方便下一个验证时提示Xxx的库存不足
          mapParams.put("goods_id",mapDB.get("goods_id"));//第2个参数是查询数据库返回的含有的字段
          mapParams.put("inventory",mapDB.get("inventory"));//从数据库里查询库存量,若存在库存量时则处理，否则不处理
          mapParams.put("spec_img",mapDB.get("spec_img"));//商品规格图片
          mapParams.put("spec_name",mapDB.get("spec_name"));//商品规格名称
          mapParams.put("goods_img",mapDB.get("goods_img"));//商品图片
          break;
        }
      }
    }
  }

  /**
   * ③验证购买的商品的数量是否有足够的库存量
   * @param listParams 注意元素的key为inventory和number
   * @作者 田应平
   * @QQ 444141300
   * @创建时间 2023/7/31 11:59
  */
  private String examineInventory(final List<HashMap<String,Object>> listParams){
    for(int x = listParams.size() - 1; x >= 0; x--){
      final HashMap<String,Object> map = listParams.get(x);
      final Integer inventory = (Integer)map.get("inventory");//库存量
      final Integer number = (Integer)map.get("number");//购买量
      if(number > inventory){
        return ToolClient.createJsonFail("商品["+map.get("goodsName")+"]库存量小于购买数量,购买失败");
      }
    }
    return null;
  }

  private String getBody(final String mode,final int allTotal){
    switch (mode){
      case "1":
        return "微信支付购买商品数量"+allTotal;
      case "2":
        return "积分支付购买商品数量"+allTotal;
      default:
        return "购买商品";
    }
  }

  public String addNotify(final HttpServletRequest request){
    return CompletableFuture.supplyAsync(()->{
      try {
        final String notifyInfo = ToolSPWechat.getNotifyInfo(request);
        if(notifyInfo != null){
          final HashMap<String,String> map = ToolSPWechat.extractParam(notifyInfo);
          final String[] attachs = map.get("attach").split(",");//数据格式:订单号、下单人;
          final long outTradeNo = Long.parseLong(attachs[0]);//订单号
          final long loginId = Long.parseLong(attachs[1]);//下单人
          final HashMap<String,Object> mapOrder = new HashMap<>(4);
          mapOrder.put("transaction_id",map.get("transaction_id"));
          mapOrder.put("total_fee",map.get("total_fee"));
          mapOrder.put("out_trade_no",outTradeNo);
          mapOrder.put("loginId",loginId);
          final int rows = apiBuyDao.updateMallOrder(mapOrder);
          if(rows > 0){
            apiBuyDao.addAddressWechat(outTradeNo);//微信支付成功时用户订单的收货地址
            ToolQuartz.deleteJob(String.valueOf(outTradeNo),MallDeleteOrder.groupName);//设定定时35(35分钟 = 2100 = 60 x 35)分钟后未支付的订单则删除,当然在支付成功回调时也可以删除定时任务的!
          }
        }
        return ToolSPWechat.failure();
      } catch (final Exception exception) {
        exception.printStackTrace();
      }
      return ToolSPWechat.failure();
    },taskExecutor).join();
  }

  public String listDataPage(final HttpServletRequest request){
    final Long loginId = LocalUserId.getLong();
    return CompletableFuture.supplyAsync(()->{
      if(loginId == null){
        return ToolClient.accessLogin();
      }
      final PageFormData formData = ToolClient.pageParamsApi(request);
      if(formData == null){
        return ToolClient.jsonValidateField();
      }
      formData.put("loginId",loginId);
      final String status = formData.getString("status");
      formData.remove("status");
      if(status != null){
        switch (status){//1待确认收货;2已完成;3待发货;不传则是全部
          case "1":
            formData.put("complete",2);
            formData.put("cargo_status",1);
            break;
          case "2"://已完成
            formData.put("cargo_status",2);
            break;
          case "3"://待发货
            formData.put("complete",1);
            formData.put("cargo_status",1);
            break;
        }
      }
      return ToolClient.jsonPage(apiBuyDao.listDataPage(formData));
    },taskExecutor).join();
  }

  public String queryOrderInfo(final Long kid,final Long out_trade_no){
    final Long loginId = LocalUserId.getLong();
    return CompletableFuture.supplyAsync(()->{
      if(loginId == null){
        return ToolClient.accessLogin();
      }
      if(kid == null || out_trade_no == null){
        return ToolClient.jsonValidateField();
      }
      final HashMap<String,Object> map = apiBuyDao.queryOrderInfo(kid);
      final HashMap<String,Long> params = new HashMap<>(2);
      params.put("loginId",loginId);
      params.put("outTradeNo",out_trade_no);
      final HashMap<String,Object> logistics = apiBuyDao.getOrderLogistics(params);
      final List<HashMap<String,Object>> list = apiBuyDao.getListDetails(out_trade_no);
      final HashMap<String,Object> result = new HashMap<>(3);
      result.put("goodsOrder",map);
      result.put("logistics",logistics);
      result.put("orderDetails",list);
      return ToolClient.queryJson(result);
    },taskExecutor).join();
  }

  public String updateCargo(final String type,final String out_trade_no){
    final Long loginId = LocalUserId.getLong();
    return CompletableFuture.supplyAsync(()->{
      if(loginId == null){
        return ToolClient.accessLogin();
      }
      if(out_trade_no == null || type == null){
        return ToolClient.jsonValidateField();
      }
      final HashMap<String,Long> params = new HashMap<>(3);
      params.put("loginId",loginId);
      params.put("out_trade_no",Long.parseLong(out_trade_no));
      return ToolClient.executeRows(apiBuyDao.edit_affirm_delivery(params));
    },taskExecutor).join();
  }
}